/*
 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.io;

import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import sun.nio.cs.StreamEncoder;


/**
 * OutputStreamWriter是一个从字符流到字节流的桥梁:
 * 写入到它的字符使用指定的Charset成为字节。
 * 它使用的字符集可以通过名称指定或明确给出，也可以接受平台的默认字符集。
 *
 * <p> 对write()方法的每次调用都会导致在给定字符上调用编码转换器。
 * 在写入底层输出流之前，生成的字节在缓存中累积。
 * 可以指定此缓冲区的大小，但默认情况下，它对于大多数用途来说已经足够大了。
 * 注意，传递给write()方法的字符没有缓冲。
 *
 * <p> 为了提高效率，可以考虑在BufferedWriter中
 * 封装一个OutputStreamWriter，以避免频繁的转换器调用。例如:
 *
 * <pre>
 * Writer out
 *   = new BufferedWriter(new OutputStreamWriter(System.out));
 * </pre>
 *
 * <p> surrogate pair对是由两个字符值序列表示的字符:
 * '\uD800'到'\uDBFF'范围内的高代理项，然后是'\uDC00'到'\uDFFF'范围内的低代理项。
 *
 * <p> 畸形代理项元素是后面没有低代理项的高代理项，或前面没有高代理项的低代理项。
 *
 * <p> 这个类总是用字符集的默认替换序列替换不规范的代理项元素和不可映射的字符序列。
 * 当需要对编码过程进行更多控制时，应该使用CharsetEncoder类。
 *
 * @see BufferedWriter
 * @see OutputStream
 * @see java.nio.charset.Charset
 *
 * @author      Mark Reinhold
 * @since       JDK1.1
 */

public class OutputStreamWriter extends Writer {

    private final StreamEncoder se;

    /**
     * 创建一个OutputStreamWriter，它使用charsetName。
     *
     * @param  out
     *         An OutputStream
     *
     * @param  charsetName
     *         The name of a supported
     *         {@link java.nio.charset.Charset charset}
     *
     * @exception  UnsupportedEncodingException
     *             If the named encoding is not supported
     */
    public OutputStreamWriter(OutputStream out, String charsetName)
        throws UnsupportedEncodingException
    {
        super(out);
        if (charsetName == null)
            throw new NullPointerException("charsetName");
        se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
    }

    /**
     * 创建一个使用默认字符编码的OutputStreamWriter。
     *
     * @param  out  An OutputStream
     */
    public OutputStreamWriter(OutputStream out) {
        super(out);
        try {
            se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
        } catch (UnsupportedEncodingException e) {
            throw new Error(e);
        }
    }

    /**
     * 创建一个使用给定字符集的OutputStreamWriter。
     *
     * @param  out
     *         An OutputStream
     *
     * @param  cs
     *         A charset
     *
     * @since 1.4
     * @spec JSR-51
     */
    public OutputStreamWriter(OutputStream out, Charset cs) {
        super(out);
        if (cs == null)
            throw new NullPointerException("charset");
        se = StreamEncoder.forOutputStreamWriter(out, this, cs);
    }

    /**
     * 创建一个OutputStreamWriter，它使用给定的字符集编码器。
     *
     * @param  out
     *         An OutputStream
     *
     * @param  enc
     *         A charset encoder
     *
     * @since 1.4
     * @spec JSR-51
     */
    public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
        super(out);
        if (enc == null)
            throw new NullPointerException("charset encoder");
        se = StreamEncoder.forOutputStreamWriter(out, this, enc);
    }

    /**
     * 返回当前流使用的字符编码的名称。
     *
     * <p> 如果编码具有历史名称，则返回该名称;
     * 否则返回编码的规范名称。
     *
     * <p> 如果这个实例是用构造函数OutputStreamWriter(OutputStream, String)创建的，
     *  那么对于编码来说唯一的返回的名称可能与传递给构造函数的名称不同。
     *  如果流已经关闭，此方法可能返回null。</p>
     *
     * @return The historical name of this encoding, or possibly
     *         <code>null</code> if the stream has been closed
     *
     * @see java.nio.charset.Charset
     *
     * @revised 1.4
     * @spec JSR-51
     */
    public String getEncoding() {
        return se.getEncoding();
    }

    /**
     * 将输出缓冲区刷新到基础字节流，而不刷新字节流本身。
     * 此方法仅是非私有的，因此可能会被PrintStream调用。
     */
    void flushBuffer() throws IOException {
        se.flushBuffer();
    }

    /**
     * 只写一个字符。
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(int c) throws IOException {
        se.write(c);
    }

    /**
     * 写入一个字符数组。
     *
     * @param  cbuf  Buffer of characters
     * @param  off   Offset from which to start writing characters
     * @param  len   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(char cbuf[], int off, int len) throws IOException {
        se.write(cbuf, off, len);
    }

    /**
     * 写入一个字符串的一部分。
     *
     * @param  str  A String
     * @param  off  Offset from which to start writing characters
     * @param  len  Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(String str, int off, int len) throws IOException {
        se.write(str, off, len);
    }

    /**
     * 刷新流
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void flush() throws IOException {
        se.flush();
    }

    public void close() throws IOException {
        se.close();
    }
}
